package jack.handler;

import android.util.Log;

/**
 * created by Jack
 * email:yucrun@163.com
 * date: 2019/5/19
 * describe:
 *
 * 2.1.Looper包含两个方法(参考源码)prepare()和myLooper()；
 * 2.2.myLooper():需要用到ThreadLocal，创建ThreadLocal对象；
 * 2.3.ThreadLocal用来存放Looper，泛型定义为Looper，在myLooper()中调用(参考源码)sThreadLocal.get()；
 * 2.4.prepare()：每一个线程只有一个Looper对象(参考源码思路)，根据判断条件，使当前线程和Looper对象绑定；
 * 2.5.loop()方法：消息轮训，该方法中需要使用到MessageQueue(消息队列)；
 * 2.6.创建MessageQueue类，Looper中持有MessageQueue(mQueue)对象，在Looper构造中初始化MessageQueue(mQueue)；
 * 2.7.在loop()方法中获取当前线程的MessageQueue(mQueue)对象;
 * 2.8.源码注释中：在调用Looper前一定要执行prepare()方法，在loop()中增加对Looper(me)的非空判断；
 * 2.9.回到handler类中,查看1.11;
 * 2.10.执行MessageQueue[queue]的Next方法,得到Message后，执行Message的转发方法；
 *
 * 2.11.回到Message类中，定义转发相关的属性和方法；
 * 2.12.发送消息的handler和接收消息的handler是同一个handler，在Handler的sendMessage方法中要指定一下接收Message的target属性，即回到Handler类中；
 *
 * 2.13.在loop()方法中，调用Message的target的dispatchMessage方法。由于Message的target就是Handler，所以Message的转发方法定义在Handler中；
 * 2.14.回到Handler中，查看dispatchMessage方法；
 *
 */
public class Looper {

    MessageQueue mQueue;

    public Looper() {
        this.mQueue = new MessageQueue();
    }

    //mThreadLocal，多个线程共享，使用static
    static ThreadLocal<Looper> sThreadLocal = new ThreadLocal<>();

    /**
     * 返回当前线程绑定的Looper对象
     * @return
     */
    public static Looper myLooper() {
//        Log.i("Handler ", "1234" + "myLooper");
        return sThreadLocal.get();
    }

    /**
     * 创建looper对象
     */
    public static void prepare() {

       // Log.i("Handler ", "1235" + "prepare");

        if (sThreadLocal.get() != null) {
            //每一个线程只有一个Looper对象，源码是这样设计的，但自己可以改造，使一个线程具有多个对象，暂时先跟着源码的思路进行实现handler
            throw new RuntimeException("Only one Looper may be created per thread");
        }

        //没有Looper的情况下，让当前线程绑定Looper对象
        sThreadLocal.set(new Looper());

    }

    /**
     * 消息轮训器
     */
    public static void loop() {
        //每一个线程有一个Looper，源码上使用了final修饰
        final Looper me = myLooper();
        if (me == null) {
            //调用Looper前，一定要执行prepare()方法
            throw new RuntimeException("No Looper; Looper.prepare() wasn't called on this thread.");
        }
        //Looper上有一个MessageQueue，源码上使用了final修饰
        MessageQueue queue = me.mQueue;

        for(;;){
            //执行queue的Next方法,拿到该条消息
            final Message msg = queue.Next();           //源码使用final方法

            //使用msg的target实现转发[参考源码]
            //转发：   发送消息的handler和接收消息的handler是同一个handler，在Handler的sendMessage方法中要指定一下Message的target

            //增加判断
            if(msg == null){
                continue;
            }

            //调用Message的target的转发消息的方法
            msg.target.dispatchMessage(msg);

        }

    }

}
